import ScalaForTheImpatient.Example._

import scala.util.Random

/**
  * Created by lovepocky(lovepocky@foxmail.com) on 2015/11/2.
  */
class ScalaForTheImpatient {
	/** scala for the impatient */
	//	new Example12_3
	new Example13
	
	
	val isTest_Example_4 = false
	val isTest_Example_5 = false
	val isTest_Example_6 = false
	val isTest_Example_8 = false
	val isTest_Example_9 = false
	val isTest_Example_10 = false
	val isTest_Example_12 = false
	val isTest_Example_13 = false
	
	val isTest_Practice_3_1 = false
	val isTest_Practice_3_2 = false
	
	/**
	  * Chapter 3: Practice
	  */
	if (isTest_Practice_3_1) {
		println("===== Practice 3.1 ======")
		getRandomArray(11).foreach(println)
		def getRandomArray(n: Int): Array[Int] = {
			for (i <- new Array[Int](n)) yield Random.nextInt(n)
		}
	}
	if (isTest_Practice_3_2) {
		println("===== Practice 3.2 ======")
		convertAdjacent(Array(1, 2, 3, 4, 5)).foreach(println(_))
		def convertAdjacent(a: Array[Int]): Array[Int] = {
			for (i <- 0 until a.length if i % 2 == 1) {
				val temp = a(i)
				a(i) = a(i - 1)
				a(i - 1) = temp
			}
			a
		}
	}
	
	/**
	  * Chapter 4: 
	  */
	if (isTest_Example_4) {
		println("===== Example 4.1 ======")
		val scores = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)
		println("immutable scores: " + scores)
		
		println("===== Example 4.2 ======")
		println("Bob In Scores: " + scores("Bob"))
		
		val bobScore2 = if (scores.contains("Bob")) scores("Bob") else 0
		println("Scores.contains(\"Bob\"): " + bobScore2)
		
		val bobScore3 = scores.getOrElse("Bob", 0)
		println("Scores.getOrElse(\"Bob\"): " + bobScore3)
		
		println("===== Example 4.3 ======")
		val newScores = scores +("Bob" -> 10, "Fred" -> 7)
		println("newScores(Bob: refreshed, Fred: added)) : " + newScores)
		
		println("===== Example 4.4 ======")
		println("keySet of Scores: " + scores.keySet)
		println("Values of Scores: " + scores.values)
		val reverseOfScores = for ((k, v) <- scores) yield (v, k)
		println("reverse(key and value) of Scores: " + reverseOfScores)
		
		println("===== Example 4.5 ======")
		//默认的映射实现为hash map
		val scoresSortedMap = scala.collection.immutable.SortedMap("Alice" -> 10, "Fred" -> 7, "Bob" -> 3, "Cindy" -> 8)
		println(scoresSortedMap)
		
		println("===== Example 4.6 ======")
		import scala.collection.JavaConversions.mapAsScalaMap
		val scoresScalaHashmap: scala.collection.mutable.Map[String, Int] = new java.util.TreeMap[String, Int]
		
		import java.awt.font.TextAttribute._

		import scala.collection.JavaConversions.mapAsJavaMap
		val attrs = Map(FAMILY -> "Serif", SIZE -> 12) //scala map
		val font = new java.awt.Font(attrs)
		println("Scala Map Convert to Java: " + font)
		
		println("===== Example 4.7 ======")
		println("Tuple: " +(1, 3.14, "Fred"))
		println("Tuple._2: " + (1, 3.14, "Fred")._2)
		
		println("===== Example 4.8 ======")
	}
	
	/**
	  * Chapter 5: 
	  */
	if (isTest_Example_5) {
		println("===== Example 5.1 ======")
		class Counter {
			private var value = 0
			
			def increment() {
				value += 1
			}
			
			def current = value
		}
		
		val myCounter = new Counter
		myCounter.increment()
		println(myCounter.current)
		
		println("===== Example 5.2 ======")
		class Person {
			private var privateAge = 0
			
			def age = privateAge
			
			def age_=(newValue: Int): Unit = {
				println("age_= called")
				if (newValue > privateAge) privateAge = newValue
			}
		}
		val fred = new Person
		
		println(fred.age)
		fred.age = 30
		fred.age = 21
		println(fred.age)
		
		println("===== Example 5.3 ======")
		class Message {
			val timeStamp = new java.util.Date
		}
		
		val message = new Message
		println(message.timeStamp)
		
		println("===== Example 5.4 ======")
		
		println("===== Example 5.5 ======")
		import scala.beans.BeanProperty
		class Person_5_5 {
			@BeanProperty
			var name: String = _
		}
		
		val person_5_5 = new Person_5_5
		person_5_5.setName("Bob")
		println(person_5_5.getName)
		person_5_5.name = "Bill"
		println(person_5_5.name)
		
		println("===== Example 5.6 ======")
		class Person_5_6 {
			private var name = ""
			private var age = 0
			
			def this(name: String) {
				this
				this.name = name
			}
			
			def this(name: String, age: Int) {
				this(name)
				this.age = age
			}
			
			override def toString: String = {
				"name = " + name + ", age = " + age
			}
			
		}
		
		val person_5_6 = new Person_5_6("Fred", 42)
		println(person_5_6)
		
		println("===== Example 5.7 ======")
		class Person_5_7(val name: String, val age: Int) {
			println("Just constructed another person")
			
			def description = name + " is " + age + " years old"
		}
		
		val person_5_7 = new Person_5_7("Gate", 100)
		println(person_5_7.description)
		
		println("===== Example 5.8 ======")
	}
	
	/**
	  * Chapter 6: 
	  */
	if (isTest_Example_6) {
		println("===== Example 6.1 ======")
		object Account {
			println("object Account Constructed")
			private var lastNumber = 0
			
			def newUniqueNumber() = {
				lastNumber += 1;
				lastNumber
			}
		}
		println(Account.newUniqueNumber())
		println(Account.newUniqueNumber())
		
		println("===== Example 6.2 ======")
		class Account {
			println("class Account Instanced")
			val id = Account.newUniqueNumber()
			private var balance = 0.0
			
			def deposit(amount: Double) {
				balance += amount
			}
			
		}
		val account = new Account
		account.deposit(100)
		println(account.id)
		
		println("===== Example 6.3 ======")
		abstract class UndoableAction(val descripton: String) {
			def undo(): Unit
			
			def redo(): Unit
		}
		
		object DoNothingAction extends UndoableAction("Do nothing") {
			override def undo(): Unit = {
				println("undo")
			}
			
			override def redo(): Unit = {
				println("redu")
			}
		}
		
		val action = Map("open" -> DoNothingAction, "save" -> DoNothingAction)
		action("open").undo()
		
		println("===== Example 6.4 ======")
		class Account_6_4 private(val id: Int, initialBalance: Double) {
			private var balance = initialBalance
			
			println("class Account_6_4 Constructed: balance = " + balance)
			
			def deposit(amount: Double) {
				balance += amount
			}
		}
		
		object Account_6_4 {
			println("object Account_6_4 Constructed")
			
			def apply(initialBalance: Double): Account_6_4 = {
				new Account_6_4(newUniqueNumber(), initialBalance)
			}
			
			private var lastNumber = 0
			
			def newUniqueNumber() = {
				lastNumber += 1;
				lastNumber
			}
		}
		val newAccount = Account_6_4(1000)
		
		println("===== Example 6.5 ======")
		
		println("===== Example 6.6 ======")
		object TrafficLightColor extends Enumeration {
			val Red, Yellow, Green = Value
			val white = Value(0xffffff)
		}
		println(TrafficLightColor.Yellow)
		println(TrafficLightColor(1))
		println(TrafficLightColor.withName("Yellow"))
		for (color <- TrafficLightColor.values) {
			println(color + ": 0x" + Integer.toHexString(color.id))
		}
		
	}
	
	/**
	  * Chapter 8
	  */
	if (isTest_Example_8) {
		println("===== Example 8.10 ======")
		class Creature {
			val range: Int = 10
			val env: Array[Int] = new Array[Int](range)
			val testNormal: Int = range
			lazy val testLazy: Int = range
		}
		
		class Ant extends Creature {
			override val range: Int = 2
		}
		
		class AntAdvanced extends {
			override val range = 2
		} with Creature
		
		val ant = new Ant
		println(ant.testNormal)
		println(ant.testLazy)
		val antAdvanced = new AntAdvanced
		println(antAdvanced.testNormal)
		println(antAdvanced.testLazy)
	}
	
	/**
	  * Chapter 9
	  */
	if (isTest_Example_9) {
		println("===== Example 9.9 ======")
	}
	
	/**
	  * Chapter 10
	  */
	if (isTest_Example_10) {
		println("===== Example 10.5 ======")
		class Account {
			var balance = 0.0
			
			def deposit(money: Double) = balance += money
		}
		class SavingAccount extends Account with Logged {
			def withdraw(amount: Double): Unit = {
				if (amount > balance) log("Insufficient funds")
				else balance -= amount
			}
		}
		trait Logged {
			def log(msg: String) {}
		}
		trait ConsoleLogger extends Logged {
			override def log(msg: String): Unit = {
				println(msg)
			}
		}
		
		trait TimestampLogger extends Logged {
			override def log(msg: String): Unit = {
				super.log(new java.util.Date() + " " + msg)
			}
		}
		trait ShortLogger extends Logged {
			val maxLength = 15
			
			override def log(msg: String): Unit = {
				super.log(
					if (msg.length <= maxLength) msg
					else msg.substring(0, maxLength - 3) + "..."
				)
			}
		}
		
		val account1 = new SavingAccount with ConsoleLogger with TimestampLogger with ShortLogger
		val account2 = new SavingAccount with ConsoleLogger with ShortLogger with TimestampLogger
		account1.withdraw(1)
		account2.withdraw(1)
		
		println("===== Example 10.10 ======")
		trait AbstractLogger {
			val AbstractVal: Int = 0
			println("Construct AbstractLogger and AbstractVal: " + AbstractVal)
		}
		
		class Account_10_10 {
			println("Construct Account_10_10")
		}
		
		val a = new {
			override val AbstractVal = 1
		} with Account_10_10 with AbstractLogger
	}
	
	/** Chapter 12 */
	if (isTest_Example_12) {
		
	}
	
	/** Chapter 13 */
	if (isTest_Example_13) {
		
		
	}
}
package ScalaForTheImpatient.Example {

class Example12_3 {
	/** ex:p154 */
	def valueAtOneQuarter(f: (Double) => Double) = f(0.25)
	
	import scala.math._
	
	val ceilValue = valueAtOneQuarter(ceil)
	val sqrtValue = valueAtOneQuarter(sqrt)
	println(ceilValue)
	println(sqrtValue)
	
	def mulBy(factor: Double) = (x: Double) => factor * x
	
	val quintuple = mulBy(5)
	println(quintuple(20))
}

class Example13 {
	def digits(n: Int): Set[Int] = {
		if (n < 0) digits(-n)
		else if (n < 10) Set(n)
		else digits(n / 10) + (n % 10)
	}
	
	digits(13247).foreach(println)
	
	def numsFrom(n: BigInt): Stream[BigInt] = n #:: numsFrom(n + 1)
	
	val tenOrMore = numsFrom(10)
	println(tenOrMore)
	val squares = numsFrom(1).map(x => x * x)
	println(squares.takeWhile(_ < 100).force)
	
	val s: Stream[BigInt] = 1 #:: s
	println(s.take(5).force)
	
	import scala.math.pow
	
	val powers = (0 until 1000).view.map(pow(10, _))
	println(powers(100))
}
	
}

package ScalaForTheImpatient.Exercise {

class ExerciseOfChpater4_1 {
	val map = Map("book" -> 10, "gun" -> 18, "pad" -> 1000)
	val discount = for ((v, k) <- map) yield (v, k * 0.9)
	println(map)
	println(discount)
	for (i@2 <- List(1, 2, 3)) {
		println
	}
}
	
}